home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / SCRNFLIP.ASM < prev    next >
Assembly Source File  |  1986-03-01  |  13KB  |  372 lines

  1. ; This program is described in BYTE, November 1983, Pages 99 - 116.
  2. ; Article is entitled "ENHANCING SCREEN DISPLAYS FOR THE IBM PC",
  3. ; author is Tim Field.
  4.  
  5. ; Define interrupt vectors for both keyboard interrupt 16H and screen
  6. ; interrupt 10H.  Both are in segment 0:
  7.  
  8. KEYVECT       SEGMENT    AT 0             ;Define KEYBOARD int. vector
  9.           ORG    16H*4
  10.           KEYINT    LABEL DWORD
  11. KEYVECT       ENDS
  12.  
  13. SCRVECT       SEGMENT    AT 0             ;Define SCREEN int. vector
  14.           ORG    10H*4
  15.           SCRINT    LABEL DWORD
  16. SCRVECT       ENDS
  17.  
  18. ; Define constants:
  19.  
  20.           BW_VAL         EQU  07H         ;Standard B&W attribute
  21.           EQUIP_FLAG     EQU  410H         ;RAM address of equipment stat
  22.           CHK_MODE         EQU  15         ;INT fn: Check screen mode
  23.           MONO_MODE      EQU  7         ;Mode 7 = monochrome monitor
  24.           COLOR_ADPT     EQU  3         ;Modes 0-3: non-graphics color
  25.  
  26. ; Start code area:
  27.  
  28. CODE          SEGMENT    PARA             ;Start code at offset 100H
  29.           ASSUME    CS:CODE          ;from starting segment; leaves
  30.           ORG    100H             ;room for PSP
  31. KEY          PROC    FAR
  32.  
  33. ; Initialization code - used only once during startup:
  34.  
  35. START:
  36.           JMP    INIT_CODE         ;Call initialization routine
  37.  
  38. ; Define storage areas and data structures:
  39. ; Define keystroke scan codes for the five SCREEN functions:
  40.  
  41.           FORE_INC         DW   5E00H      ;Foreground increment
  42.           BACK_INC         DW   6000H      ;Background increment
  43.           C80_40         DW   6200H      ;80x25 to 40x25 flip-flop key
  44.           COL_MON         DW   6400H      ;COLOR/MONO flip-flop key
  45.           REPAINT         DW   6600H      ;Repaint scrn using curr. mode
  46.           CUR_MODE         DW   COL80_AREA     ;Initialize starting mode
  47.           MONO_SET         DW   MONO_AREA     ;Pointer to monochrome area
  48.           COLOR_SET      DW   COL80_AREA     ;Pointer to active color area
  49.           SCRN_ATTR      DB   70H         ;Current screen attribute
  50.           SCRN_MODE      DB   255         ;Save current screen mode
  51.  
  52. ; Define structure used to contain information about 40 and 80 column color
  53. ; modes as well as monochrome mode:
  54.  
  55. S STRUC
  56.           CORNER         DW   0         ;Defines COL/ROW count of
  57.                          ;characters for the monitor
  58.           BF         DW   0         ;Colors of FORE and BACK
  59.           EQUIP         DW   0         ;Equipment setting
  60.           MODE         DW   0         ;AX value for setting the mode
  61. S ENDS                         ;of the monitor
  62.  
  63. ; Now set up three screen structures with default condition:
  64.  
  65.   COL80_AREA  S     <5019H,0107H,20H,3>     ;80x25 white FORE, blue BACK
  66.   COL40_AREA  S     <2819H,0107H,10H,1>     ;40x25 brown FORE, black BACK
  67.   MONO_AREA   S     <5019H,0007H,30H,7>     ;Monochrome, reverse video
  68.  
  69. KEY_CALL:     DB   0EAH              ;Far JMP address to KEYBOARD
  70.           DD   0                 ;interrupt.  See article
  71.  
  72. ; Procedure KEY_RTNE intercepts keyboard interrupt and determines if the
  73. ; keystroke is one of the five SCREEN ones:
  74.  
  75. KEY_RTNE:
  76.           STI                 ;Turn on interrupts
  77.           CMP    AH,0
  78.           JNE    KEY_CALL
  79.           PUSH    DS             ;Save registers
  80.           PUSH    BX
  81.           PUSH    CX
  82.           PUSH    DX
  83.           PUSH    ES
  84.           PUSH    DI
  85.           PUSH    CS             ;Point DS to CS segment by
  86.           POP    DS             ;PUSH / POP operation
  87.           ASSUME    DS:CODE
  88. INT_LOOP:                     ;IBM keyboard procedure
  89.           PUSHF                 ;expects an interrupt call
  90.           MOV    BX,OFFSET KEY_CALL+1     ;Address to ROM keyboard code
  91.           CALL    DWORD PTR [BX]         ;Call keyboard routine
  92.           MOV    BX,CUR_MODE         ;Get current mode address
  93.           CMP    AX,COL_MON         ;See if COLOR/MON flip flop
  94.           JNE    TEST_FORE         ;key.    Exit if not. Otherwise:
  95.           CMP    BX,MONO_SET         ;Flip flop screen mode
  96.           JE    SET_COLOR         ;If monochrome, swap to color
  97.           CMP    MONO_SET,0         ;See if monochrome installed
  98.           JE    NEXT_KEY         ;Ignore command if not
  99.           MOV    BX,MONO_SET         ;Otherwise set up monochrome
  100.           JMP    SHORT DO_CHG
  101. SET_COLOR:
  102.           CMP    COLOR_SET,0         ;See if COLOR monitor enabled
  103.           JE    NEXT_KEY         ;Skip if not
  104.           MOV    BX,COLOR_SET         ;Set up for color
  105. DO_CHG:
  106.           CALL    SCREEN_CHG         ;Implement screen change
  107. NEXT_KEY:
  108.           MOV    AH,0             ;Set up to fetch keystroke
  109.           JMP    INT_LOOP         ;Fetch next key input
  110. TEST_FORE:
  111.           PUSH    AX             ;Save registers
  112.           PUSH    BX             ;See if in GRAPHICS mode
  113.           MOV    AH,CHK_MODE
  114.           INT    10H
  115.           POP    BX             ;Restore BX register
  116.           CMP    AL,COLOR_ADPT         ;If between 0-3, not graphics
  117.           JLE    NOT_GRAPH
  118.           CMP    AL,MONO_MODE         ;Monochrome mode
  119.           JGE    NOT_GRAPH
  120.           POP    AX             ;Restore stack
  121.           JMP    DONE             ;If color-graphics mode, do
  122. NOT_GRAPH:                     ;not change modes
  123.           POP    AX             ;Restore AX
  124.           CMP    AX,FORE_INC         ;Increment FOREGROUND color?
  125.           JNE    TEST_BACK         ;Skip if not
  126.           CMP    BX,COLOR_SET         ;See if currently using color
  127.           JNE    BW_FLOP          ;If not, go deal with B&W
  128.           MOV    AX,[BX].BF         ;Gets BACK in AL, FORE in AH
  129. EQ_FORE:
  130.           INC    AL             ;Increment FOREGROUND color
  131.           AND    AL,7             ;Keep it within bounds
  132.           CMP    AL,AH             ;See if same as BACKGROUND
  133.           JE    EQ_FORE          ;Increment again if yes
  134.           MOV    [BX].BF,AX         ;Save back to structure
  135.           JMP    DO_CHG             ;Redraw the screen
  136. TEST_BACK:
  137.           CMP    AX,BACK_INC         ;Increment BACKGROUND color?
  138.           JNE    TEST_REPAINT         ;Skip if not
  139.           CMP    BX,COLOR_SET         ;See if currently using color
  140.           JNE    BW_FLOP          ;If not, go deal with B&W
  141.           MOV    AX,[BX].BF         ;Gets BACK in AL, FORE in AH
  142. EQ_BACK:
  143.           INC    AH             ;Increment BACKGROUND color
  144.           AND    AH,7             ;Keep it within bounds
  145.           CMP    AH,AL             ;See if same as FOREGROUND
  146.           JE    EQ_BACK          ;Increment again if yes
  147.           MOV    [BX].BF,AX         ;Save back to structure
  148.           JMP    DO_CHG             ;Redraw the screen
  149. BW_FLOP:                     ;Flip flop B&W monitor
  150.           MOV    AX,[BX].BF         ;BACK in AH, FORE in Al
  151.           XCHG    AH,AL             ;Swap FOREGROUND, BACKGROUND
  152.           MOV    [BX].BF,AX         ;Save back to structure
  153.           JMP    DO_CHG             ;Redraw the screen
  154. TEST_REPAINT:
  155.           CMP    AX,REPAINT         ;Repaint the screen?
  156.           JE    DO_CHG             ;If yes, then repaint screen
  157. TEST_80_40:
  158.           CMP    AX,C80_40         ;80-40 flip flop key?
  159.           JNE    DONE             ;Exit if not
  160.           CMP    BX,OFFSET COL40_AREA     ;Is curr. pointer area 40x25?
  161.           JNE    TST80             ;Skip if not
  162.           MOV    BX,OFFSET COL80_AREA     ;Otherwise, flip to 80x25
  163.           JMP    SHORT SAVE_COL         ;Save to COLOR_SET
  164. TST80:
  165.           CMP    BX,OFFSET COL80_AREA     ;Is current 80x25 color?
  166.           JNE    NEXT_KEY         ;Ignore key if not
  167.           MOV    BX,OFFSET COL40_AREA
  168. SAVE_COL:
  169.           MOV    COLOR_SET,BX         ;Save to COLOR_SET
  170.           JMP    SET_COLOR         ;Implement
  171. DONE:
  172.           POP    DI             ;Restore registers
  173.           POP    ES
  174.           POP    DX
  175.           POP    CX
  176.           POP    BX
  177.           POP    DS
  178.           IRET                 ;Return from interrupt
  179. KEY          ENDP                 ;End of main routine
  180.  
  181. ; This routine changes current monitor screen mode.  On input, BX points to
  182. ; the current monitor structure:
  183.  
  184. SCREEN_CHG    PROC    NEAR
  185.           MOV    AX,0             ;Get segment address for RAM
  186.           MOV    ES,AX             ;EQUIP_FLAG
  187.           MOV    AX,ES:EQUIP_FLAG     ;Get set of EQUIP flags
  188.           AND    AL,0CFH          ;Scrap current monitor flag
  189.           OR    AX,[BX].EQUIP         ;Set up new monitor flag
  190.           MOV    ES:EQUIP_FLAG,AX     ;Save back in RAM
  191.           MOV    CUR_MODE,BX         ;Indicate new mode
  192.  
  193. ; Now set up attribute for FOREGROUND and BACKGROUND:
  194.  
  195.           MOV    DX,[BX].BF         ;Get both FORE and BACK in DX
  196.           MOV    CL,4             ;Shift count
  197.           SHL    DH,CL             ;Shift BACK into upper nibble
  198.           OR    DH,DL             ;Move FORE into lower nibble
  199.           MOV    SCRN_ATTR,DH         ;Save results
  200.  
  201. ; See if we need to reset monitor (switching to new monitor?):
  202.  
  203.           MOV    AX,[BX].MODE         ;Get screen mode
  204.           CMP    AL,SCRN_MODE         ;Compare with current mode
  205.           JE    SET_ATTR         ;Skip if the same
  206.           MOV    SCRN_MODE,AL         ;Otherwise, save current mode
  207.           INT    10H             ;And reset to new monitor
  208. SET_ATTR:
  209.           CALL    CH_ATTR          ;Change attributes of current
  210.           RET                 ;screen
  211. SCREEN_CHG    ENDP
  212.  
  213. ; This routine repaints the active screen so that every character on the
  214. ; current screen is displayed with the new attributes.    On input, BX points
  215. ; to the current monitor structure:
  216.  
  217. CH_ATTR       PROC    NEAR
  218.  
  219. ; See if we need to redraw border for color mode
  220.  
  221.           CMP    BX,OFFSET MONO_SET     ;In color?
  222.           JE    NO_BORDER         ;Skip border code if not
  223.           PUSH    AX             ;Save registers
  224.           PUSH    BX
  225.           MOV    BX,[BX].BF         ;Get BACKGROUND color in BL
  226.           MOV    BL,BH
  227.           MOV    BH,0             ;Select border coloring
  228.           MOV    AH,11             ;Fn. call: set color palette
  229.           INT    10H             ;Execute VIDEO I/O interrupt
  230.           POP    BX             ;Restore registers
  231.           POP    AX
  232. NO_BORDER:
  233.           MOV    AX,[BX].CORNER         ;Get COL and ROW for current
  234.           MOV    CORNR,AX         ;Save in temporary data area
  235.           MOV    AH,CHK_MODE         ;Get page number
  236.           INT    10H
  237.  
  238. ; BX contains the active page:
  239.  
  240.           MOV    AH,3             ;Get current cursor position
  241.           INT    10H
  242.           PUSH    DX             ;Save position on stack
  243.           XOR    DX,DX             ;Zero-out DX
  244.           MOV    CX,1             ;Set up counter
  245.           MOV    BL,SCRN_ATTR         ;Get current attribute
  246. REP_ATTR:
  247.           MOV    AH,2             ;Set cursor position
  248.           INT    10H
  249.           MOV    AH,8             ;Read next character
  250.           INT    10H
  251.  
  252. ; AH contains the current character attribute:
  253.  
  254.           AND    AH,88H             ;Get intensity bit
  255.           AND    BL,77H             ;Ensure attr. intensity is off
  256.           OR    BL,AH             ;Create current attribute
  257.           MOV    AH,9             ;Display char. with new attr.
  258.           INT    10H
  259.           INC    DL
  260.           CMP    DL,TCOL          ;Are we done with this column?
  261.           JLE    REP_ATTR         ;If so, jump
  262.           XOR    DL,DL             ;Otherwise, zero-out DL
  263.           INC    DH             ;Move to next row
  264.           CMP    DH,TROW          ;Are we done with this screen?
  265.           JLE    REP_ATTR         ;Loop until done
  266.           POP    DX             ;Restore orig. cursor position
  267.           MOV    AH,2
  268.           INT    10H
  269.           RET
  270.           CORNR    LABEL      WORD
  271.           TROW    DB      0         ;Temp. store for ROW
  272.           TCOL    DB      0         ;Temp. store for COL
  273. CH_ATTR       ENDP
  274.  
  275. ; This routine replaces the SCREEN interrupt so that it can intercept B&W
  276. ; character writes and change the display attributes:
  277.  
  278. SCR_RTNE      PROC    NEAR
  279.           STI
  280.           PUSH    DS             ;Save DS
  281.           PUSH    CS             ;Point DS to CS segment by
  282.           POP    DS             ;PUSH / POP operation
  283.           ASSUME    DS:CODE
  284.           CMP    AH,6             ;Spot SCROLLUP and SCROLLDOWN
  285.           JL    NORMAL_SCR         ;calls
  286.           CMP    AH,7
  287.           JG    NOT_SCROLL
  288. SCROLL:
  289.           CALL    GET_CH             ;Update attribute for scroll
  290.           JMP    NORMAL_SCR         ;Now execute scroll
  291. NOT_SCROLL:
  292.           CMP    AH,9             ;Check for "WRITE ATTR / CHAR"
  293.           JNE    NORMAL_SCR         ;command.  Send out any other
  294.           XCHG    BH,BL             ;commands as normal. Get attr.
  295.           CALL    GET_CH             ;in BL and update attribute
  296.           XCHG    BH,BL             ;Move attribute back to BH for
  297. NORMAL_SCR:                     ;command
  298.           POP    DS             ;Restore DS segment register
  299. JMP_SCR:      DB    0EAH             ;See article
  300.           DD    0
  301. SCR_RTNE      ENDP
  302.  
  303. ; This routine replaces the B&W character with the current replacement
  304. ; attributes and allows for the INTENSITY bit setting.    On input, BH
  305. ; contains the attribute to be modified:
  306.  
  307. GET_CH          PROC    NEAR
  308.           MOV    SAVECH,BH         ;Save character
  309.           AND    BH,77H             ;Remove intensity / blink bits
  310.           CMP    BH,BW_VAL         ;See if cur. defined B&W value
  311.           MOV    BH,SAVECH         ;Otherwise, modify to current
  312.           JNE    OUT             ;attribute.  Exit if not
  313.           AND    BH,88H             ;Get rid of B&W part
  314.           OR    BH,SCRN_ATTR         ;Move in current attr. part
  315. OUT:
  316.           RET                 ;Done
  317.           SAVECH    DB   0             ;Temporary character store
  318. GET_CH          ENDP
  319.  
  320. ; All code after this label is freed to DOS use after this program has been
  321. ; initialized:
  322.  
  323. LASTONE:
  324.  
  325. ; This routine loads and initializes the SCREEN program.  It sets up DOS to
  326. ; keep all code before the label LASTONE safe from overlay during normal
  327. ; system operation:
  328.  
  329. INIT_CODE     PROC    NEAR
  330.  
  331. ; Initialize KEYBOARD intercept code:
  332.  
  333.           MOV    AX,KEYVECT         ;Point ES to interrupt vectors
  334.           MOV    ES,AX             ;(segment at 0H)
  335.           ASSUME    ES:KEYVECT
  336.           MOV    AX,ES:KEYINT         ;Get address of interrupt
  337.           MOV    BX,OFFSET KEY_CALL+1     ;vector and save both the
  338.           MOV    [BX],AX          ;segment and offset values of
  339.           MOV    AX,ES:KEYINT[2]      ;this routine in our data area
  340.           MOV    [BX+2],AX         ;Now, replace the original
  341.           MOV    ES:KEYINT,OFFSET KEY_RTNE ;interrupt vector with the
  342.           MOV    AX,CS             ;address of our own routine
  343.           MOV    ES:KEYINT[2],AX
  344.  
  345. ; Initialize SCREEN intercept code:
  346.  
  347.           MOV    AX,SCRVECT         ;Point ES to interrupt vectors
  348.           MOV    ES,AX             ;(segment at 0H)
  349.           ASSUME    ES:SCRVECT
  350.           MOV    AX,ES:SCRINT         ;Get address of interrupt
  351.           MOV    BX,OFFSET JMP_SCR+1     ;vector and save both the
  352.           MOV    [BX],AX          ;segment and offset values of
  353.           MOV    AX,ES:SCRINT[2]      ;this routine in our data area
  354.           MOV    [BX+2],AX         ;Now, replace the original
  355.           MOV    ES:SCRINT,OFFSET SCR_RTNE ;interrupt vector with the
  356.           MOV    AX,CS             ;address of our own routine
  357.           MOV    ES:SCRINT[2],AX
  358.  
  359. ; Initialize screen:
  360.  
  361.           MOV    BX,CUR_MODE         ;Set up initial screen mode
  362.           CALL    SCREEN_CHG         ;Initialize screen mode
  363.  
  364. ; Now, terminate and stay resident:
  365.  
  366.           MOV    DX,OFFSET LASTONE     ;Save all code up to LASTONE
  367.           INT    27H             ;Terminate and stay resident
  368. INIT_CODE     ENDP
  369.  
  370. CODE          ENDS
  371.           END    START
  372.